package org.example.utils;


import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.timeout.IdleStateHandler;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.example.annotation.RpcServer;
import org.example.annotation.RpcServerScan;
import org.example.handler.PingMessageHandler;
import org.example.handler.RpcRequestMessageHandler;
import org.example.handler.RpcResponseMessageHandler;
import org.example.protocol.MessageCodec;
import org.example.protocol.ProcotolFrameDecoder;
import org.example.registery.ServerRegistry;

import java.net.InetSocketAddress;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * @description: 服务端负责接收请求，返回结果
 * @author: feixiang.li
 * @date: 2025-01-02 22:12
 */
@Data
@Slf4j
public class NettyServiceUtils {


    private int port;
    private String host;

    private NioEventLoopGroup worker = new NioEventLoopGroup();
    private NioEventLoopGroup boss = new NioEventLoopGroup();
    private ServerBootstrap bootstrap = new ServerBootstrap();
    protected ServerRegistry serverRegistry;

    /**
     * 服务注册中心-nacos或者zookeeper
     */
    private ServiceFactory serviceFactory = new ServiceFactory();

    /**
     * 启动类
     */
    private Class<?> mainClass;

    /**
     * 构造函数
     *
     * @param host           ip
     * @param port           port
     * @param serverRegistry 服务注册中心
     * @param clazz          启动类
     */
    public NettyServiceUtils(String host, int port, ServerRegistry serverRegistry, Class<?> clazz) {
        this.host = host;
        this.port = port;
        this.serverRegistry = serverRegistry;
        this.mainClass = clazz;
    }


    /**
     * 启动服务端
     */
    public void start() {
        // 第一步，扫描注解，获得服务类
        scanService();
        log.error("扫描服务成功");
        // 查看注册的信息
        ServiceUtils.serviceRegistry.forEach((k, v) -> {
            log.error("key:{},value:{}", k, v);
        });
        // 第二步：创建bootstrap
        startBootstrap();
    }

    /**
     * 扫描@RpcServer注解 注册服务
     */
    void scanService() {
        // 获取启动类main函数的路径
        String mainClassPath = mainClass.getName();
        // 获取main方法上 注解的值
        String annotationValue = mainClass.getAnnotation(RpcServerScan.class).value();
        //如果注解路径的值是空，则等于main父路径包下
        if ("".equals(annotationValue)) {
            annotationValue = mainClassPath.substring(0, mainClassPath.lastIndexOf("."));
        }
        //获取所有类的set集合
        Set<Class<?>> set = PackageScanUtils.getClasses(annotationValue);
        log.info("获取到类:{}个", set.size());
        for (Class<?> c : set) {
            //只有有@RpcServer注解的才注册
            if (c.isAnnotationPresent(RpcServer.class)) {
                String ServerNameValue = c.getAnnotation(RpcServer.class).name();
                Object object;
                try {
                    object = c.newInstance();
                } catch (InstantiationException | IllegalAccessException e) {
                    log.error("创建对象" + c + "发生错误", e);
                    continue;
                }
                //注解的值如果为空，使用类名
                if ("".equals(ServerNameValue)) {
                    // 获取到接口信息，而非注册实体类名称
                    Class<?>[] interfaces = object.getClass().getInterfaces();
                    addServer(object, interfaces[0].getName());
                } else {
                    addServer(object, ServerNameValue);
                }
            }
        }
    }

    public void addServer(Object server, String serverName) {
        // 只有一个实现类才可以注册
        serviceFactory.addServiceProvider(server, serverName);
        serverRegistry.register(serverName, new InetSocketAddress(host, port));
    }

    void startBootstrap() {
        //心跳处理器
//        HeartBeatServerHandler heartBeatServerHandler = new HeartBeatServerHandler();
        // 创建bootstrap
        try {
            bootstrap.group(boss, worker)
                    .channel(NioServerSocketChannel.class)
                    .option(ChannelOption.SO_BACKLOG, 256)
                    .option(ChannelOption.SO_KEEPALIVE, true)
                    .option(ChannelOption.TCP_NODELAY, true)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            ChannelPipeline pipeline = ch.pipeline();
                            // 添加日志
                            pipeline.addLast(new LoggingHandler(LogLevel.DEBUG));
                            // 心跳处理器
                            pipeline.addLast(new IdleStateHandler(30, 0, 0, TimeUnit.SECONDS));
                            pipeline.addLast(new ProcotolFrameDecoder());//定长解码器
                            // 消息解码器
                            pipeline.addLast(new MessageCodec());
                            // 添加rpc请求处理器
                            pipeline.addLast(new RpcRequestMessageHandler());
                            // 添加ping消息处理器
                            pipeline.addLast(new PingMessageHandler());
                        }
                    });
            //绑定端口
            Channel channel = bootstrap.bind(port).sync().channel();
            channel.closeFuture().sync();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            log.error("服务端启动失败-InterruptedException", e);
        } catch (Exception e) {
            log.error("服务端启动失败", e);
        } finally {
            boss.shutdownGracefully();
            worker.shutdownGracefully();
        }
    }
}
